package TCP;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EchoServer {
    private ServerSocket serverSocket;

    public EchoServer(int port) throws IOException {
        //服务器启动，就会绑定到 port 端口上面。
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器上线！");

        while(true) {
            //接收一个客户端请求
            Socket socket = serverSocket.accept();


            //一个线程处理一个连接，这样服务器可以被多个客户端连接。
            Thread t = new Thread(() -> {
               this.processCoonection(socket);
            });

            t.start();
        }
    }

    //处理一个客户端/一个连接的逻辑.
    public void processCoonection(Socket socket) {
        System.out.printf("[%s:%d] 客户端上线！\n",socket.getInetAddress().toString(),socket.getPort());

        //实现通信的代码逻辑
        //获取与客户端连接的输入流和输出流
        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream()) {

            //创建一个 Scanner 对象，用它从输入流 inputStream 读取客户端发送的请求数据
            Scanner scanner = new Scanner(inputStream);
            //创建一个 PrintWriter 对象，利用它把响应数据写入输出流 outputStream
            PrintWriter writer = new PrintWriter(outputStream);

            while(true) {
                //一、读取请求并解析。
                if(!scanner.hasNext()) {
                    // 针对客户端下线逻辑的处理. 如果客户端断开连接了 (比如客户端结束了)
                    // 此时 hasNext 就会返回 false
                    System.out.printf("[%s:%d] 客户端下线！\n", socket.getInetAddress().toString(), socket.getPort());
                    break;
                }
                String request = scanner.next();

                //二、根据请求计算响应。
                String response = process(request);

                //三、把响应写回客户端。
                writer.println(response);
                //刷新缓冲区
                writer.flush();

                System.out.printf("[%s:%d] req: %s; resp: %s\n", socket.getInetAddress().toString(), socket.getPort(), request, response);
            }
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //防止文件资源泄露
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //这里由于是回显服务器，直接返回结果。
    public String process(String request) {

        return request;
    }

    public static void main(String[] args) throws IOException {
        EchoServer echoServer = new EchoServer(9090);
        echoServer.start();
    }
}
